package com.qiujianwei.study.authcenter.auth;

import com.qiujianwei.sdk.Entity.Payload;
import com.qiujianwei.sdk.common.util.auth.JwtUtil;
import com.qiujianwei.sdk.common.util.auth.RsaUtil;
import com.qiujianwei.sdk.redis.RedisCache;
import com.qiujianwei.study.authcenter.common.contract.Rsa.RsaProperties;
import com.qiujianwei.study.authcenter.entity.LoginUser;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.server.context.ServerSecurityContextRepository;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Map;

import static com.qiujianwei.study.authcenter.common.contract.auth.PathEnum.LOGIN_PATH;

@Component
public class CustomSecurityContextRepository implements ServerSecurityContextRepository {

    private final static String KEY_PREFIX = "user_power:";

    @Autowired
    private RedisCache redisCache;


    @Override
    public Mono<Void> save(ServerWebExchange exchange, SecurityContext context) {
        return Mono.empty();
    }

    @Override
    public Mono<SecurityContext> load(ServerWebExchange exchange) {
        //1.过滤掉登陆请求
        String path = exchange.getRequest().getPath().toString();
        if (LOGIN_PATH.path.equals(path)) {
            return Mono.empty();
        }
        //2、获取token
        String token = exchange.getRequest().getHeaders().getFirst(HttpHeaders.AUTHORIZATION);

        //3.解析token并生成认证凭证
        Payload<Integer> tokenInfo = null;
        try {
            tokenInfo = JwtUtil.getInfoFromToken(token, RsaUtil.getPublicKey(RsaProperties.publicKey.getBytes()), Integer.class);
        } catch (Exception e) {
            e.printStackTrace();
            return Mono.empty();
        }
        List<String> powerList = redisCache.getCacheList(KEY_PREFIX + tokenInfo.getUserInfo());
        LoginUser loginUser = new LoginUser();
        loginUser.setPowers(powerList);
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null);
        //4.将不守信的凭证转换成受信凭证后
        CustomReactiveAuthenticationManager customReactiveAuthenticationManager = new CustomReactiveAuthenticationManager();
        Mono<Authentication> authenticate = customReactiveAuthenticationManager.authenticate(usernamePasswordAuthenticationToken);
        //5.返回上下文对象
        return authenticate.map(SecurityContextImpl::new);
    }
}
